//======================================================================================================================
// 2007 Copyright Mystic Lake Software
//
// This file is part of The Ham Radio Network.
//
// The Ham Radio Network is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// The Ham Radio Network is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//======================================================================================================================
//
//     Author: Rudyard Merriam
//
//      $Id: nibbleconvert.cpp 6 2007-10-04 07:01:34Z k5rud@arrl.net $
//
//======================================================================================================================
//
#include <iostream>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;

#include <stdio.h>
#include <fcntl.h>
#include <io.h>

#include "member_fun.h"
//----------------------------------------------------------------------------------------------------------------------
void byte2nibble(const char& ch)
{
    cout << (unsigned char(ch) >> 4) << (ch & 0x0F);
}
//----------------------------------------------------------------------------------------------------------------------
class Nibble2Byte
{
public:
    Nibble2Byte() : mIsFirst(true) { }

    void encode(const char& ch)
    {
        cout << (unsigned char(ch) >> 4) << (ch & 0x0F);
    }

    void decode(const char& ch)
    {
        char nibble = (ch - '0');
        if (nibble > 9)
        {
            nibble = ch - 'a' + 10;
        }

        if (mIsFirst)
        {
            mCh = (nibble << 4);
            mIsFirst = false;
        }
        else
        {
            mCh |= nibble;
            mIsFirst = true;
            cout << mCh;
        }
    }
    char mCh;
    bool mIsFirst;
};
//----------------------------------------------------------------------------------------------------------------------
typedef istreambuf_iterator<char> char_in;
//======================================================================================================================
int main(int argc, char *argv[])
{
    if (argc == 2)
    {
        Nibble2Byte n2b;
        if (argv[1][0] == 'E')
        {
            hex(cout);
            _setmode(_fileno(stdin), _O_BINARY);
            for_each((char_in(cin)), char_in(), member_fun(n2b, &Nibble2Byte::encode));
        }
        else if (argv[1][0] == 'D')
        {
            _setmode(_fileno(stdout), _O_BINARY);
            for_each((char_in(cin)), char_in(), member_fun(n2b, &Nibble2Byte::decode));
        }
    }
    else
    {
        cerr << "(E)ncode or (D)ecode option missing" << endl;
    }
}
